package org.wcf.util;

import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wuchaofei
 * @date 2016/3/23
 */
public class FileUtil {
    /**
     * 从php文件采集function 信息
     * @return
     */
    public static Map<String,Object> phpFunctions(String path){
        Map<String,Object> funMap=new TreeMap<String,Object>();
        BufferedReader br = null;

        try {
            br = new BufferedReader(new FileReader(path));
            String line="";
            String functionName = null;
            while(line!=null) {
                line = br.readLine();
                if(StringUtils.isNotEmpty(line)){
                    line = line.trim();
                    //逻辑处理
                    String name = collectEachFunctionMsg(line, functionName, funMap);
                    if(name!=null){
                        functionName = name;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(br != null) br.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(funMap);

        return funMap;
    }
    /**
     * 从line中提取function 信息
     * @param funMap
     */
    private static String collectEachFunctionMsg(String line,String functionName,Map<String, Object> funMap) {

        if(funMap==null){
            funMap =new HashMap<String, Object>();
        }

        String name = getActionName(line,false);
        if(name!=null){
            functionName=name;
            //function 开始
            funMap.put(functionName,new TreeMap<String,Object>());

            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);

            //将提取的className放入functionMap
            function.put("className",getClassName(functionName));
            //提取参数
            function.put("param",getParams(functionName));
            //functionName 放入
            function.put("funName",splitAndUpperFirst(functionName));
        }

        String selectLine = getSelect(line);
        if(null!=selectLine){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            function.put("select",selectLine);
        }
        Map whereLine = getWhere(line);
        if(null!=whereLine){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            Map whereMap = (Map<String,String>) function.get("where");
            if(whereMap==null){
                whereMap=new TreeMap<String,String>();
            }

            whereMap.putAll(whereLine);
            function.put("where", whereMap);
        }
        Map whereIn = getWhereIn(line);
        if(null!=whereIn){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            Map whereInMap = (Map<String,String>) function.get("where_in");
            if(whereInMap==null){
                whereInMap=whereIn;
            }else{
                whereInMap.putAll(whereIn);
            }
            function.put("where_in", whereInMap);
        }
        Map<String, String> orderByLine = getOrderBy(line);
        if(null!=orderByLine){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            Map<String, String> orderByMap = (Map<String, String>) function.get("orderBy");
            if(orderByMap==null){
                orderByMap=new TreeMap<String,String>();
            }
            orderByMap.putAll(orderByLine);
            function.put("orderBy", orderByMap);
        }
        String limitLine = getLimit(line);
        if(null!=limitLine){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            function.put("limit",limitLine);
        }
        String fromLine = getFrom(line);
        if(null!=fromLine){
            Map<String,Object> function = (Map<String, Object>) funMap.get(functionName);
            function.put("from",fromLine);
        }
        return name;
    }

    /**
     * 获取action name
     * @param line
     * @return
     */
    public static String getActionName(String line,boolean join) {
//        function get_product_by_pid( $pid = "" ){
        return getLineFunctionName(line,"(public)?\\s{0,}function\\s+([a-zA-Z0-9_]+)\\s{0,}\\(.{0,}\\)\\s{0,}\\{?",2,join);
    }

    public static String getSelect(String line){
//        $this->db->select('pid,title,subtitle,group_id,property_ids,extra_info,seo_title,seo_keywords,seo_description,category_id,is_can_buy,url,extra_info,product_ext');
        if(line.contains("select")){
            int start=line.indexOf("('")+2;
            int end = line.indexOf("')");
            return line.substring(start,end);
        }
        return null;
    }
    public static String getFrom(String line){
//        $this->db->from('articles');
        if(line.contains("from")){
            int start=line.indexOf("('")+2;
            int end = line.indexOf("')");
            return line.substring(start,end);
        }
        return null;
    }

    public static Map getWhere(String line){
//        $this->db->where('pid',$pid);
        Map<String, String> map = new TreeMap<String, String>();
        if(line.contains("where") && !line.contains("where_in")){
            int start=line.indexOf("(");
            int end = line.lastIndexOf(")");
            String keyValue=line.substring(start, end);
            keyValue=keyValue.replaceAll("[\'\"\\(\\)]","");
            String[] arr = keyValue.split(",");
            map.put(arr[0],arr[1]);
            return map;
        }
        return null;
    }
    public static Map getWhereIn(String line){
//        $this->db->where('pid',$pid);
        Map<String, String> map = new TreeMap<String, String>();
        if(line.contains("where_in")){
            int start=line.indexOf("(");
            int end = line.lastIndexOf(")");
            String keyValue=line.substring(start, end);
            keyValue=keyValue.replaceAll("[\'\"\\(\\)]","");
            String[] arr = keyValue.split(",");
            map.put(arr[0],arr[1]);
            return map;
        }
        return null;
    }
    public static Map<String, String> getOrderBy(String line){
//        $this->db->order_by('sorts','ASC');
        Map<String, String> map = new TreeMap<String, String>();
        if(line.contains("order_by")){
            int start=line.indexOf("(")+1;
            int end = line.lastIndexOf(")");
//            $this->db->order_by($order,$sort);
            line=line.substring(start,end).replaceAll("'","").replaceAll("\"","");
            String[] arr = line.split(",");
            map.put(arr[0], arr[1]);
            return map;
        }
        return null;
    }

    public static String getLimit(String line){
//        $this->db->limit(1);
        if(line.contains("limit")){
            int start=line.indexOf("(")+1;
            int end=line.indexOf(")");
            return line.substring(start,end);
        }
        return null;
    }


    /**
     * 获取每行的function name
     * @param line 行
     * @param regex 正则
     * @param group 分组
     * @return
     */
    public static String getLineFunctionName(String line,String regex,int group){
        return getLineFunctionName(line,regex,group,false);
    }
    public static String getLineFunctionName(String line,String regex,int group,boolean join){
        line=line.trim();
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(line);
        if(matcher.matches()) {
            String str = matcher.group(group);
            return str.startsWith("_")?null:join?splitAndUpperFirst(str):str;
        }
        return null;
    }


    /**
     * 根据"_"分割字符串，拼接起来
     * @param s 源字符串
     * @param upperfirst 是否字符串第一个字母大写，默认分割后的word首字母大写
     * @return
     */
    public static String splitAndUpperFirst(String s,boolean upperfirst){
        String[] arr = s.split("_");
        StringBuffer sb=new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            if(i==0 && !upperfirst){
                sb.append(arr[i].substring(0,1)).append(arr[i].substring(1));
            }else{
                sb.append(arr[i].substring(0,1).toUpperCase()).append(arr[i].substring(1));
            }
        }
        return sb.toString();
    }
    /**
     * 根据"_"分割字符串，拼接起来
     * @param s 源字符串
     * @return
     */
    public static String splitAndUpperFirst(String s){
        return splitAndUpperFirst(s,false);
    }


    /**
     * 截取className,get_product_by_id
     * @param fun
     * @return
     */
    public static String getClassName(String fun){
        fun=fun.replace("get_","");
        if(fun.contains("by_")){
            fun = fun.substring(0,fun.indexOf("by_"));
        }
        return splitAndUpperFirst(fun,true);
    }

    /**
     * 截取参数数组
     * @param fun
     * @return
     */
    public static List<String> getParams(String fun){
        fun=fun.replace("get_","");
        if(fun.contains("by_")){
            fun = fun.substring(fun.indexOf("by_")+3);
        }
        return Arrays.asList(fun.split("_"));
    }
}
